#!/usr/bin/env python

import unit

from helper import get_prop

class GameError(Exception):
  def __init__(self, value):
    self.value = value
  
  def __str__(self):
    return repr(self.value)

class Player:
  def __init__(self, name, engine, *args, **properties):
    self.name = name
    self.engine = engine
    self.long_name = get_prop(properties, 'long_name', 'Anonymous')
    self.flag = get_prop(properties, 'flag', def_val=None) #Animation
    self.color = get_prop(properties, 'color', must_exist=True) #hex string
    self.unit_list = []
  
  def is_enemy(self, other):
    self_team = self.engine.get_team(self)
    other_team = self.engine.get_team(other)
    return self_team == other_team
  
  def is_ally(self, other):
    return not self.is_enemy(other)
  
  def register_unit(self, unit):
    if unit not in self.unit_list:
      self.unit_list.append(unit)
  
  def get_color(self):
    return self.color
  
  def __eq__(self, other):
    return self.name == other.name
  
  def __ne__(self, other):
    return not self.__eq__(other)
  
  def __str__(self):
    return '<Player: %s - %s>' % (self.name, self.long_name)

class GameEngine:
  def __init__(self, unit_engine):
    self.player_list = { }
    self.unit_engine = unit_engine
    self.started = False
  
  def get_all_players(self):
    return reduce(lambda p_list, p: p_list + self.player_list[p], self.player_list, [])
  
  def get_players_by_team(self, team):
    return self.player_list[team]
  
  def has_player(self, player_name):
    for team, players in self.player_list.iteritems():
      if player in players:
        return True
    return False
  
  def get_team(self, player):
    for team, players in self.player_list.iteritems():
      if player in players:
        return team
    raise GameError('No such player registered: %s' % (player))
  
  def register_player(self, player, team=None):
    if started:
      raise GameError('Game has already started, cannot add new players.')
    def create_team(team=None):
      if team is not None and team in self.player_list:
        return team
      i = 0
      if team is None:
        while True:
          team = 'Team %d' % (i)
          if team not in self.player_list:
            break
          i += 1
      self.player_list[team] = []
      return team
    
    team = create_team(team)
    self.player_list[team].append(player)
    player.set_engine(self)
  
  def start(self):
    
    self.turn_list = self.get_all_players()
    self.started = True
  
  #Called by the game to denote the end of one turn, and the start
  #of another
  def turn(next=None):
    prev = self.turn_list[len(self.turn_list) - 1]
    if next is None:
      next = self.turn_list.pop(0)
    else:
      #next = self.turn_list.pop(self.turn_list.index(player))
      self.turn_list.pop(self.turn_list.index(next))
    
    
    #set to state normal for the previous player
    for unit in prev.unit_list:
      unit_engine.update_unit(unit)
    
    
    self.turn_list.append(next)
